#include "Message.h"
#include <sstream>
#include "MessageDescriptor.h"
#include "ProtoField.h"
#include "ProtoFieldDescriptor.h"
#include "BufferStream.h"
#include "ProtoUtil.h"

namespace miniproto
{

Message::Message()
{
	this->message_descriptor_ = NULL;
	this->field_list_ = new ProtoFieldList();
	this->message_factory_ = NULL;
}

Message::~Message()
{
	if (this->field_list_ != NULL)
	{
		for (ProtoFieldList::iterator iter = this->field_list_->begin();
				iter != this->field_list_->end(); ++iter)
		{
			delete (*iter);
		}
		delete this->field_list_;
		this->field_list_ = NULL;
	}
}

const ::std::string &Message::GetTypeName() const
{
	return this->message_descriptor_->GetTypeName();
}

void Message::Clear(void)
{
	for (ProtoFieldList::iterator iter = this->field_list_->begin();
			iter != this->field_list_->end(); ++iter)
	{
		if ((*iter)->is_field_set())
			(*iter)->Clear();
	}
}

int Message::ByteSize() const
{
	int size = 0;
	uint32_t number = 0;
	for (ProtoFieldList::const_iterator iter = this->field_list_->begin();
			iter != this->field_list_->end(); ++iter)
	{
		++number;
		const ::miniproto::ProtoField *field = *iter;
		if (field->is_field_set() == false) continue;
		size += field->ByteSize(number);
	}
	return size;
}

void Message::CopyFrom(const ::miniproto::Message &from)
{
	if (&from == this) return;
	if (this->message_descriptor_ != from.message_descriptor_) return;
	Clear();
	MergeFrom(from);
}

void Message::MergeFrom(const ::miniproto::Message &from)
{
	if (this->message_descriptor_ != from.message_descriptor_) return;
	if (this->field_list_->size() != from.field_list_->size()) return;
	int field_size = this->field_list_->size();
	for (int i = 0; i < field_size; ++i)
	{
		::miniproto::ProtoField* to_field = this->field_list_->at(i);
		const ::miniproto::ProtoField* from_field = from.field_list_->at(i);
		if (from_field->is_field_set() == false)
			continue;
		if (to_field->field_type() != from_field->field_type())
			continue;
		to_field->copy(*from_field);
	}
}

bool Message::ParseFromArray(const void *data, int size)
{
	this->Clear();
	BufferStream stream(const_cast<void *>(data), size);
	while (stream.left_read_size() > 0)
	{
		uint32_t wire_tag = 0, number = 0;
		int32_t wire_type = 0;
		if (stream.read_tag(&wire_tag) == false)
			return false;
		::miniproto::wire_tag_split(wire_tag, &number, &wire_type);
		::miniproto::ProtoField *field = NULL;
		const ::miniproto::ProtoFieldDescriptor *field_descriptor = NULL;
		if (0 < number && number <= this->field_list_->size())
		{
			field = this->field_list_->at(number -1);
			field_descriptor = this->message_descriptor_->get_field_desc(number);
		}
		switch(wire_type)
		{
			case ::miniproto::ProtoFieldDescriptor::WIRE_VARINT:
			{
				if (this->parse_varint(field, field_descriptor, stream) == false)
					return false;
				break;
			}
			case ::miniproto::ProtoFieldDescriptor::WIRE_FLOAT:
			{
				if (this->parse_float(field, field_descriptor, stream) == false)
					return false;
				break;
			}
			case ::miniproto::ProtoFieldDescriptor::WIRE_DOUBLE:
			{
				if (this->parse_double(field, field_descriptor, stream) == false)
					return false;
				break;
			}
			case ::miniproto::ProtoFieldDescriptor::WIRE_STRING_OR_MESSAGE:
			{
				if (this->parse_string_or_message(field, field_descriptor, stream) == false)
					return false;
				break;
			}
			default:
			{
				return false;
				break;
			}
		}
	}
	return true;
}

bool Message::parse_varint(::miniproto::ProtoField *field, const ::miniproto::ProtoFieldDescriptor *field_descriptor, BufferStream &stream)
{
	uint64_t val;
	if (stream.read_varint64(&val) == false)
		return false;
	if (field == NULL || field_descriptor == NULL)
		return true;
	if (field_descriptor->is_array())
	{
		switch(field_descriptor->base_field_type())
		{
			case ::miniproto::ProtoFieldDescriptor::BOOL:
				field->add_field_bool(static_cast<bool>(val));
				break;
			case ::miniproto::ProtoFieldDescriptor::INT32:
				field->add_field_int32(static_cast<int32_t>(val));
				break;
			case ::miniproto::ProtoFieldDescriptor::INT64:
				field->add_field_int64(static_cast<int64_t>(val));
				break;
			case ::miniproto::ProtoFieldDescriptor::UINT32:
				field->add_field_uint32(static_cast<uint32_t>(val));
				break;
			case ::miniproto::ProtoFieldDescriptor::UINT64:
				field->add_field_uint64(val);
				break;
			default:
				break;
		}
	}
	else
	{
		switch(field_descriptor->base_field_type())
		{
			case ::miniproto::ProtoFieldDescriptor::BOOL:
				field->set_field_bool(static_cast<bool>(val));
				break;
			case ::miniproto::ProtoFieldDescriptor::INT32:
				field->set_field_int32(static_cast<int32_t>(val));
				break;
			case ::miniproto::ProtoFieldDescriptor::INT64:
				field->set_field_int64(static_cast<int64_t>(val));
				break;
			case ::miniproto::ProtoFieldDescriptor::UINT32:
				field->set_field_uint32(static_cast<uint32_t>(val));
				break;
			case ::miniproto::ProtoFieldDescriptor::UINT64:
				field->set_field_uint64(val);
				break;
			default:
				break;
		}
	}
	return true;
}

bool Message::parse_float(::miniproto::ProtoField *field, const ::miniproto::ProtoFieldDescriptor *field_descriptor, BufferStream &stream)
{
	float val;
	if (stream.read_float(&val) == false)
		return false;
	if (field == NULL || field_descriptor == NULL)
		return true;
	if (field_descriptor->is_array())
	{
		field->add_field_float(val);
	}
	else
	{
		field->set_field_float(val);
	}
	return true;
}

bool Message::parse_double(::miniproto::ProtoField *field, const ::miniproto::ProtoFieldDescriptor *field_descriptor, BufferStream &stream)
{
	double val;
	if (stream.read_double(&val) == false)
		return false;
	if (field == NULL || field_descriptor == NULL)
		return true;
	if (field_descriptor->is_array())
	{
		field->add_field_double(val);
	}
	else
	{
		field->set_field_double(val);
	}
	return true;
}

bool Message::parse_string_or_message(::miniproto::ProtoField *field, const ::miniproto::ProtoFieldDescriptor *field_descriptor, BufferStream &stream)
{
	uint64_t size = 0;
	if (stream.read_varint64(&size) == false)
		return false;
	if (size > static_cast<uint64_t>(stream.left_read_size()))
		return false;
	BufferStream sub_stream(stream.read_ptr(), size);
	if (stream.read_buffer(size) == false)
		return false;
	if (field == NULL || field_descriptor == NULL)
		return true;
	uint8_t base_type = field_descriptor->base_field_type();
	if (base_type == ::miniproto::ProtoFieldDescriptor::STRING ||
			base_type == ::miniproto::ProtoFieldDescriptor::BYTES)
	{
		return parse_string(field, field_descriptor, size, sub_stream);
	}
	else if (base_type == ::miniproto::ProtoFieldDescriptor::MESSAGE)
	{
		return parse_message(field, field_descriptor, size, sub_stream);
	}
	return true;
}

bool Message::parse_string(::miniproto::ProtoField *field, const ::miniproto::ProtoFieldDescriptor *field_descriptor, const uint64_t size, BufferStream &stream)
{
	if (field_descriptor->is_array())
	{
		::std::string *val = new ::std::string();
		if (stream.read_string(val, size) == false)
			return false;
		field->add_field_string(val);
	}
	else
	{
		if (stream.read_string(field->get_field_string(), size) == false)
			return false;
		field->set_field_set(true);
	}
	return true;
}

bool Message::parse_message(::miniproto::ProtoField *field, const ::miniproto::ProtoFieldDescriptor *field_descriptor, const uint64_t size, BufferStream &stream)
{
	if (field_descriptor->is_array())
	{
		::miniproto::Message *val = field_descriptor->NewMessage();
		if (val == NULL)
			return false;
		if (val->ParseFromArray(stream.read_ptr(), size) == false)
			return false;
		field->add_field_message(val);
	}
	else
	{
		if (field->get_field_message()->ParseFromArray(stream.read_ptr(), size) == false)
			return false;
		field->set_field_set(true);
	}
	return true;
}

bool Message::ParseFromString(const ::std::string &data)
{
	return this->ParseFromArray(data.data(), data.size());
}

bool Message::SerializeToArray(void *data, int size) const
{
	BufferStream stream(data, size);
	int index = 0;
	for (ProtoFieldList::const_iterator iter = this->field_list_->begin();
			iter != this->field_list_->end(); ++iter)
	{
		++index;
		const ::miniproto::ProtoField *field = *iter;
		if (field->is_field_set() == false) continue;
		const ::miniproto::ProtoFieldDescriptor *field_descriptor = this->message_descriptor_->get_field_desc(index);
		if (field_descriptor == NULL) continue;
		uint8_t base_type = field_descriptor->base_field_type();
		switch(base_type)
		{
			case ::miniproto::ProtoFieldDescriptor::BOOL:
			{
				if (this->serialize_bool(field, field_descriptor, stream) == false)
					return false;
				break;
			}
			case ::miniproto::ProtoFieldDescriptor::INT32:
			{
				if (this->serialize_int32(field, field_descriptor, stream) == false)
					return false;
				break;
			}
			case ::miniproto::ProtoFieldDescriptor::INT64:
			{
				if (this->serialize_int64(field, field_descriptor, stream) == false)
					return false;
				break;
			}
			case ::miniproto::ProtoFieldDescriptor::UINT32:
			{
				if (this->serialize_uint32(field, field_descriptor, stream) == false)
					return false;
				break;
			}
			case ::miniproto::ProtoFieldDescriptor::UINT64:
			{
				if (this->serialize_uint64(field, field_descriptor, stream) == false)
					return false;
				break;
			}
			case ::miniproto::ProtoFieldDescriptor::FLOAT:
			{
				if (this->serialize_float(field, field_descriptor, stream) == false)
					return false;
				break;
			}
			case ::miniproto::ProtoFieldDescriptor::DOUBLE:
			{
				if (this->serialize_double(field, field_descriptor, stream) == false)
					return false;
				break;
			}
			case ::miniproto::ProtoFieldDescriptor::STRING:
			case ::miniproto::ProtoFieldDescriptor::BYTES:
			{
				if (this->serialize_string(field, field_descriptor, stream) == false)
					return false;
				break;
			}
			case ::miniproto::ProtoFieldDescriptor::MESSAGE:
			{
				if (this->serialize_message(field, field_descriptor, stream) == false)
					return false;
				break;
			}
			default:
				break;
		}
	}
	return true;
}

bool Message::serialize_varint(const uint32_t wire_tag, const uint64_t val, BufferStream &stream) const
{
	if (stream.write_tag(wire_tag) == false)
		return false;
	if (stream.write_varint64(val) == false)
		return false;
	return true;
}

bool Message::serialize_bool(const ::miniproto::ProtoField *field, const ::miniproto::ProtoFieldDescriptor *field_descriptor, BufferStream &stream) const
{
	uint32_t wire_tag = field_descriptor->wire_tag();
	if (field_descriptor->is_array())
	{
		const ::miniproto::ProtoField::BoolList *bool_list = field->get_field_bool_list();
		typedef ::miniproto::ProtoField::BoolList::const_iterator BoolListIter;
		for (BoolListIter iter = bool_list->begin(); iter != bool_list->end(); ++iter)
		{
			uint64_t val = ((*iter) ? 1 : 0);
			if (this->serialize_varint(wire_tag, val, stream) == false)
				return false;
		}
	}
	else
	{
		uint64_t val = (field->get_field_bool() ? 1 : 0);
		if (this->serialize_varint(wire_tag, val, stream) == false)
			return false;
	}
	return true;
}

bool Message::serialize_int32(const ::miniproto::ProtoField *field, const ::miniproto::ProtoFieldDescriptor *field_descriptor, BufferStream &stream) const
{
	uint32_t wire_tag = field_descriptor->wire_tag();
	if (field_descriptor->is_array())
	{
		const ::miniproto::ProtoField::Int32List *int32_list = field->get_field_int32_list();
		typedef ::miniproto::ProtoField::Int32List::const_iterator Int32ListIter;
		for (Int32ListIter iter = int32_list->begin(); iter != int32_list->end(); ++iter)
		{
			uint64_t val = static_cast<uint64_t>(*iter);
			if (this->serialize_varint(wire_tag, val, stream) == false)
				return false;
		}
	}
	else
	{
		uint64_t val = static_cast<uint64_t>(field->get_field_int32());
		if (this->serialize_varint(wire_tag, val, stream) == false)
			return false;
	}
	return true;
}

bool Message::serialize_int64(const ::miniproto::ProtoField *field, const ::miniproto::ProtoFieldDescriptor *field_descriptor, BufferStream &stream) const
{
	uint32_t wire_tag = field_descriptor->wire_tag();
	if (field_descriptor->is_array())
	{
		const ::miniproto::ProtoField::Int64List *int64_list = field->get_field_int64_list();
		typedef ::miniproto::ProtoField::Int64List::const_iterator Int64ListIter;
		for (Int64ListIter iter = int64_list->begin(); iter != int64_list->end(); ++iter)
		{
			if (this->serialize_varint(wire_tag, static_cast<uint64_t>(*iter), stream) == false)
				return false;
		}
	}
	else
	{
		if (this->serialize_varint(wire_tag, static_cast<uint64_t>(field->get_field_int64()), stream) == false)
			return false;
	}
	return true;
}

bool Message::serialize_uint32(const ::miniproto::ProtoField *field, const ::miniproto::ProtoFieldDescriptor *field_descriptor, BufferStream &stream) const
{
	uint32_t wire_tag = field_descriptor->wire_tag();
	if (field_descriptor->is_array())
	{
		const ::miniproto::ProtoField::UInt32List *uint32_list = field->get_field_uint32_list();
		typedef ::miniproto::ProtoField::UInt32List::const_iterator UInt32ListIter;
		for (UInt32ListIter iter = uint32_list->begin(); iter != uint32_list->end(); ++iter)
		{
			uint64_t val = static_cast<uint64_t>(*iter);
			if (this->serialize_varint(wire_tag, val, stream) == false)
				return false;
		}
	}
	else
	{
		uint64_t val = static_cast<uint64_t>(field->get_field_uint32());
		if (this->serialize_varint(wire_tag, val, stream) == false)
			return false;
	}
	return true;
}

bool Message::serialize_uint64(const ::miniproto::ProtoField *field, const ::miniproto::ProtoFieldDescriptor *field_descriptor, BufferStream &stream) const
{
	uint32_t wire_tag = field_descriptor->wire_tag();
	if (field_descriptor->is_array())
	{
		const ::miniproto::ProtoField::UInt64List *uint64_list = field->get_field_uint64_list();
		typedef ::miniproto::ProtoField::UInt64List::const_iterator UInt64ListIter;
		for (UInt64ListIter iter = uint64_list->begin(); iter != uint64_list->end(); ++iter)
		{
			if (this->serialize_varint(wire_tag, *iter, stream) == false)
				return false;
		}
	}
	else
	{
		if (this->serialize_varint(wire_tag, field->get_field_uint64(), stream) == false)
			return false;
	}
	return true;
}

bool Message::serialize_float(const ::miniproto::ProtoField *field, const ::miniproto::ProtoFieldDescriptor *field_descriptor, BufferStream &stream) const
{
	uint32_t wire_tag = field_descriptor->wire_tag();
	if (field_descriptor->is_array())
	{
		const ::miniproto::ProtoField::FloatList *float_list = field->get_field_float_list();
		typedef ::miniproto::ProtoField::FloatList::const_iterator FloatListIter;
		for (FloatListIter iter = float_list->begin(); iter != float_list->end(); ++iter)
		{
			if (stream.write_tag(wire_tag) == false)
				return false;
			if (stream.write_float(*iter) == false)
				return false;
		}
	}
	else
	{
		if (stream.write_tag(wire_tag) == false)
			return false;
		if (stream.write_float(field->get_field_float()) == false)
			return false;
	}
	return true;
}

bool Message::serialize_double(const ::miniproto::ProtoField *field, const ::miniproto::ProtoFieldDescriptor *field_descriptor, BufferStream &stream) const
{
	uint32_t wire_tag = field_descriptor->wire_tag();
	if (field_descriptor->is_array())
	{
		const ::miniproto::ProtoField::DoubleList *double_list = field->get_field_double_list();
		typedef ::miniproto::ProtoField::DoubleList::const_iterator DoubleListIter;
		for (DoubleListIter iter = double_list->begin(); iter != double_list->end(); ++iter)
		{
			if (stream.write_tag(wire_tag) == false)
				return false;
			if (stream.write_double(*iter) == false)
				return false;
		}
	}
	else
	{
		if (stream.write_tag(wire_tag) == false)
			return false;
		if (stream.write_double(field->get_field_double()) == false)
			return false;
	}
	return true;
}

bool Message::serialize_string(const ::miniproto::ProtoField *field, const ::miniproto::ProtoFieldDescriptor *field_descriptor, BufferStream &stream) const
{
	uint32_t wire_tag = field_descriptor->wire_tag();
	if (field_descriptor->is_array())
	{
		const ::miniproto::ProtoField::StringList *string_list = field->get_field_string_list();
		typedef ::miniproto::ProtoField::StringList::const_iterator StringListIter;
		for (StringListIter iter = string_list->begin(); iter != string_list->end(); ++iter)
		{
			if (stream.write_tag(wire_tag) == false)
				return false;
			if (stream.write_string(*iter) == false)
				return false;
		}
	}
	else
	{
		if (stream.write_tag(wire_tag) == false)
			return false;
		if (stream.write_string(field->get_field_string()) == false)
			return false;
	}
	return true;
}

bool Message::serialize_message(const ::miniproto::ProtoField *field, const ::miniproto::ProtoFieldDescriptor *field_descriptor, BufferStream &stream) const
{
	uint32_t wire_tag = field_descriptor->wire_tag();
	if (field_descriptor->is_array())
	{
		const ::miniproto::ProtoField::MessageList *message_list = field->get_field_message_list();
		typedef ::miniproto::ProtoField::MessageList::const_iterator MessageListIter;
		for (MessageListIter iter = message_list->begin(); iter != message_list->end(); ++iter)
		{
			if (stream.write_tag(wire_tag) == false)
				return false;
			const Message *message = *iter;
			uint64_t msg_size = message->ByteSize();
			if (stream.write_varint64(msg_size) == false)
				return false;
			if (static_cast<uint64_t>(stream.left_write_size()) < msg_size)
				return false;
			if (message->SerializeToArray(stream.write_ptr(), msg_size) == false)
				return false;
			if (stream.write_buffer(msg_size) == false)
				return false;
		}
	}
	else
	{
		if (stream.write_tag(wire_tag) == false)
			return false;
		const Message *message = field->get_field_message();
		uint64_t msg_size = message->ByteSize();
		if (stream.write_varint64(msg_size) == false)
			return false;
		if (static_cast<uint64_t>(stream.left_write_size()) < msg_size)
			return false;
		if (message->SerializeToArray(stream.write_ptr(), msg_size) == false)
			return false;
		if (stream.write_buffer(msg_size) == false)
			return false;
	}
	return true;
}

bool Message::SerializeToString(::std::string *output) const
{
	int size = this->ByteSize();
	int old_size = output->size();
	output->resize(old_size + size);
	return this->SerializeToArray((void *)(this->string_as_array(output) + old_size), size);
}

std::string Message::SerializeAsString(void) const
{
	::std::string output;
	SerializeToString(&output);
	return output;
}

#define PRINT_BASE_LIST(SStream, ListType, ListObj) {\
	const ListType *list = ListObj; \
	typedef ListType::const_iterator ListTypeIterator; \
	int fi = 0; \
	for (ListTypeIterator iter = list->begin(); iter != list->end(); ++iter) \
	{ \
		if (fi++ > 0) SStream << ","; \
		SStream << *iter; \
	} \
}

::std::string Message::DebugString(void) const
{
	std::ostringstream ss;
	int index = 0, size = 0;
	ss << this->GetTypeName() << "{";
	for (ProtoFieldList::const_iterator iter = this->field_list_->begin();
			iter != this->field_list_->end(); ++iter)
	{
		++index;
		const ::miniproto::ProtoField *field = *iter;
		if (field->is_field_set() == false)
			continue;
		if (size++ > 0)
			ss << ",";
		const ::miniproto::ProtoFieldDescriptor *field_descriptor = this->message_descriptor_->get_field_desc(index);
		ss << field_descriptor->field_name() << " = ";
		int base_type = field_descriptor->base_field_type();
		if (field_descriptor->is_array())
		{
			ss << "[";
			switch(base_type)
			{
				case ::miniproto::ProtoFieldDescriptor::BOOL:
					PRINT_BASE_LIST(ss, ::miniproto::ProtoField::BoolList, field->get_field_bool_list());
					break;
				case ::miniproto::ProtoFieldDescriptor::INT32:
					PRINT_BASE_LIST(ss, ::miniproto::ProtoField::Int32List, field->get_field_int32_list());
					break;
				case ::miniproto::ProtoFieldDescriptor::INT64:
					PRINT_BASE_LIST(ss, ::miniproto::ProtoField::Int64List, field->get_field_int64_list());
					break;
				case ::miniproto::ProtoFieldDescriptor::UINT32:
					PRINT_BASE_LIST(ss, ::miniproto::ProtoField::UInt32List, field->get_field_uint32_list());
					break;
				case ::miniproto::ProtoFieldDescriptor::UINT64:
					PRINT_BASE_LIST(ss, ::miniproto::ProtoField::UInt64List, field->get_field_uint64_list());
					break;
				case ::miniproto::ProtoFieldDescriptor::FLOAT:
					PRINT_BASE_LIST(ss, ::miniproto::ProtoField::FloatList, field->get_field_float_list());
					break;
				case ::miniproto::ProtoFieldDescriptor::DOUBLE:
					PRINT_BASE_LIST(ss, ::miniproto::ProtoField::DoubleList, field->get_field_double_list());
					break;
				case ::miniproto::ProtoFieldDescriptor::STRING:
					{
						const ::miniproto::ProtoField::StringList *list = field->get_field_string_list();
						typedef ::miniproto::ProtoField::StringList::const_iterator ListTypeIterator;
						int fi = 0;
						for (ListTypeIterator iter = list->begin(); iter != list->end(); ++iter)
						{
							if (fi++ > 0) ss << ",";
							ss << "\"" << *iter << "\"";
						}
					}
					break;
				case ::miniproto::ProtoFieldDescriptor::BYTES:
					{
						const ::miniproto::ProtoField::StringList *list = field->get_field_string_list();
						typedef ::miniproto::ProtoField::StringList::const_iterator ListTypeIterator;
						int fi = 0;
						for (ListTypeIterator iter = list->begin(); iter != list->end(); ++iter)
						{
							if (fi++ > 0)
								ss << ",";
							std::ostringstream strss;
							const std::string *str = *iter;
							for (std::string::const_iterator str_iter = str->begin(); str_iter != str->end(); ++str_iter)
								strss << std::hex << "\\x" << (static_cast<int>(*str_iter) & 0x0ff);
							ss << strss.str();
						}
					}
					break;
				case ::miniproto::ProtoFieldDescriptor::MESSAGE:
					{
						const ::miniproto::ProtoField::MessageList *list = field->get_field_message_list();
						typedef ::miniproto::ProtoField::MessageList::const_iterator ListTypeIterator;
						int fi = 0;
						for (ListTypeIterator iter = list->begin(); iter != list->end(); ++iter)
						{
							if (fi++ > 0)
								ss << ",";
							const ::miniproto::Message *message = *iter;
							ss << message->DebugString();
						}
					}
					break;
				default:
					break;
			}
			ss << "]";
		}
		else
		{
			switch(base_type)
			{
				case ::miniproto::ProtoFieldDescriptor::BOOL:
					ss << field->get_field_bool();
					break;
				case ::miniproto::ProtoFieldDescriptor::INT32:
					ss << field->get_field_int32();
					break;
				case ::miniproto::ProtoFieldDescriptor::INT64:
					ss << field->get_field_int64();
					break;
				case ::miniproto::ProtoFieldDescriptor::UINT32:
					ss << field->get_field_uint32();
					break;
				case ::miniproto::ProtoFieldDescriptor::UINT64:
					ss << field->get_field_uint64();
					break;
				case ::miniproto::ProtoFieldDescriptor::FLOAT:
					ss << field->get_field_float();
					break;
				case ::miniproto::ProtoFieldDescriptor::DOUBLE:
					ss << field->get_field_double();
					break;
				case ::miniproto::ProtoFieldDescriptor::STRING:
					ss << "\"" << (*(field->get_field_string())) << "\"";
					break;
				case ::miniproto::ProtoFieldDescriptor::BYTES:
					{
						std::ostringstream strss;
						const std::string *str = field->get_field_string();
						for (std::string::const_iterator str_iter = str->begin(); str_iter != str->end(); ++str_iter)
							strss << std::hex << "\\x" << (static_cast<int>(*str_iter) & 0x0ff);
						ss << strss.str();
					}
					break;
				case ::miniproto::ProtoFieldDescriptor::MESSAGE:
					{
						const ::miniproto::Message *message = field->get_field_message();
						ss << message->DebugString();
					}
					break;
				default:
					break;
			}
		}
	}
	ss << "}";
	return ss.str();
}
std::string Message::Utf8DebugString(void) const
{
	return this->DebugString();
}

char *Message::string_as_array(::std::string *output) const
{
	return output->empty() ? NULL : &*output->begin();
}

const Message::ProtoFieldList *Message::field_list() const
{
	return this->field_list_;
}

int Message::FieldSize() const
{
	return this->field_list_->size();
}

const ProtoField *Message::GetField(int number) const
{
	if (0 < number && number <= this->FieldSize())
	{
		return this->field_list_->at(number - 1);
	}
	return NULL;
}

const ProtoFieldDescriptor *Message::GetFieldDescriptor(int number) const
{
	return this->message_descriptor_->get_field_desc(number);
}

}
